package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAppointment;
import cn.wolfcode.business.domain.BusServiceItem;
import cn.wolfcode.business.domain.BusStatement;
import cn.wolfcode.business.mapper.BusStatementMapper;
import cn.wolfcode.business.service.BusAppointmentService;
import cn.wolfcode.business.service.BusStatementService;
import cn.wolfcode.business.util.RegexUtils;
import cn.wolfcode.business.util.UpdateUtils;
import cn.wolfcode.business.util.VehiclePlateNoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.invoke.VarHandle;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static cn.wolfcode.business.domain.BusAppointment.STATUS_ARRIVED;
import static cn.wolfcode.business.domain.BusAppointment.STATUS_BOOKING;
import static cn.wolfcode.business.domain.BusStatement.*;

@Service
public class BusStatementServiceImpl implements BusStatementService {
    @Autowired
    BusStatementMapper busStatementMapper;

    @Override
    public List<BusServiceItem> getList(BusStatement busStatement) {
        return busStatementMapper.getList(busStatement);
    }

    /**
     * 查询一条结算单信息
     *
     * @param id
     * @return
     */
    @Override
    public BusStatement getStatement(Long id) {
        return busStatementMapper.getStatement(id);
    }


    /**
     * 新增结算单---结算单从哪来的
     * 第一如果有预约就是从预约单来的
     * 如果没有则需要填写表单
     * 也就是说只要是通过表单填写的是否预约的状态都是否  即就是不给appoint_id值为0
     * 先实现表单增加即手动增加
     *
     * @param busStatement
     * @return
     */
    @Override
    public Integer add(BusStatement busStatement) {
        //先不管先来一个填写表单即用户直接到店的新增
        //1.参数合理化
        //1.1非空校验
        if (busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
                || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null ||
                busStatement.getCarSeries() == null || busStatement.getServiceType() == null)
            throw new RuntimeException("必填参数不能为空！");
        //1.2参数合理化校验---跟预约新增的参数校验差不多--时间也有要求在当前时间之后即可，调用工具类 传入-1
        //1.2 对联系方式即电话进行格式校验
        if (RegexUtils.isPhoneLegal(busStatement.getCustomerPhone()) != true)
            throw new RuntimeException("手机号码格式不正确，请重新输入！！！");
        //1.3 对车牌号进行格式校验
        if (VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate()) == null)
            throw new RuntimeException("车牌号格式不正确，请重新输入！！！");
        //1.4 实际到店时间在当前时间之后就行，使用工具类，传入0
        Date date = UpdateUtils.addTime(new Date(), Calendar.MINUTE, -1);
        if (!date.before(busStatement.getActualArrivalTime()))
            throw new RuntimeException("不能再当前时间之前创建结算单，如有需求请先预约！");
        //确保安全创建一个中间对象
        BusStatement newBusStatement = new BusStatement();
        newBusStatement.setCustomerName(busStatement.getCustomerName());
        newBusStatement.setCustomerPhone(busStatement.getCustomerPhone());
        newBusStatement.setActualArrivalTime(busStatement.getActualArrivalTime());
        newBusStatement.setCarSeries(busStatement.getCarSeries());
        newBusStatement.setLicensePlate(busStatement.getLicensePlate());
        newBusStatement.setServiceType(busStatement.getServiceType());
        newBusStatement.setInfo(busStatement.getInfo());

        //初始结算状态为未支付
        newBusStatement.setStatus(STATUS_PAID);
        //初始化软删除字段为0
        newBusStatement.setIsDelete(DELETE_NO);
        //创建时间
        newBusStatement.setCreateTime(new Date());
        return busStatementMapper.add(newBusStatement);
    }

    /**
     * 编辑结算单
     * 参数校验差不多--主要考虑什么时候能改？有什么不能改的嘛？
     * 到店时间不让改
     *
     * @param busStatement
     * @return
     */
    @Override
    public Integer update(BusStatement busStatement) {
        //参数合理化校验---cv新增--区别实际到店时间不让改
        //1.参数合理化
        //1.1非空校验
        if (busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
                || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null ||
                busStatement.getCarSeries() == null || busStatement.getServiceType() == null)
            throw new RuntimeException("必填参数不能为空！");
        //1.2参数合理化校验---跟预约新增的参数校验差不多--时间也有要求在当前时间之后即可，调用工具类 传入-1
        //1.2 对联系方式即电话进行格式校验
        if (RegexUtils.isPhoneLegal(busStatement.getCustomerPhone()) != true)
            throw new RuntimeException("手机号码格式不正确，请重新输入！！！");
        //1.3 对车牌号进行格式校验
        if (VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate()) == null)
            throw new RuntimeException("车牌号格式不正确，请重新输入！！！");
        //1.4 实际到店时间不让改
        if (!getStatement(busStatement.getId()).getActualArrivalTime().equals(busStatement.getActualArrivalTime())) {
            throw new RuntimeException("非法操作数据,编辑时不能更改时间");
        }
        //1.4啥时候让改？根据结算状态--status 已支付不让改，消费中不让改
        if (getStatement(busStatement.getId()).getStatus() == STATUS_PAID)
            throw new RuntimeException("该结算单已支付无法修改！！");
        return busStatementMapper.update(busStatement);
    }

    /**
     * 结算单软删除，就一个判断，什么时候让删除，软删除无所谓
     *
     * @param id
     * @return
     */
    @Override
    public Integer delete(Long id) {
        //参数合理化验证
        if (id == null)
            throw new RuntimeException("非法参数");
        //根据id查询到对应的对象
        BusStatement statement = getStatement(id);
        if (statement == null)
            throw new RuntimeException("系统错误！！");
        //只有消费中的可以删除
        if (STATUS_PAID.equals(statement.getStatus())) {
            throw new RuntimeException("已支付的结算单不能删除");
        }
        //已经删除的不能再次删除
        if (DELETE_YES.equals(statement.getIsDelete()))
            throw new RuntimeException("已经删除的结算单不能再次删除！");
        return busStatementMapper.delete(id, DELETE_YES);
    }


    @Override
    public Integer Modify(Long statementId,BigDecimal totalAmount, BigDecimal totalQuantity, BigDecimal discountPrice) {
        return busStatementMapper.Modify(statementId,totalAmount, totalQuantity, discountPrice);
    }


    /**
     * 点击支付后触发，用于补全结算单表中还未填充的字段，
     * @param statementId 结算单id
     * @param userId    收款人id
     * @param date      收款时间
     * @param status    结算单状态
     * @return
     */
    @Override
    public int payUpdateStatement(Long statementId, Long userId, Date date, Integer status) {
        return busStatementMapper.payUpdateStatement( statementId,  userId,  date, status);
    }

    /**
     * 生成结算单--不需要有什么逻辑判断吗？不行，他直接发这种请求不就绕过了验证？cv重复验证
     *最终我都要返回一个结算单id
     * @param busAppointment
     * @return
     */
    @Override
    public Long generateStatement(BusAppointment busAppointment) {
        if (busAppointment == null)
            throw new RuntimeException("非法注入数据！！");
        //2.不能重复生成结算单，去重--直接返回结算单id---把状态改
        if (busStatementMapper.getBusStatementByAppointId(busAppointment.getId()) != null) {

           return busStatementMapper.getBusStatementByAppointId(busAppointment.getId()).getId();
        }
        //已到店才能生成结算单
        if (!busAppointment.getStatus().equals(STATUS_ARRIVED))
            throw new RuntimeException("已到店状态才能生成结算单！！！");
        String customerName = busAppointment.getCustomerName();
        String customerPhone = busAppointment.getCustomerPhone();
        Date actualArrivalTime = busAppointment.getActualArrivalTime();
        String licensePlate = busAppointment.getLicensePlate();
        String carSeries = busAppointment.getCarSeries();
        Integer serviceType = busAppointment.getServiceType();
        String info = busAppointment.getInfo();
        //把预约单中的信息传给结算单
        BusStatement busStatement = new BusStatement();
        busStatement.setCustomerName(customerName);
        busStatement.setCustomerPhone(customerPhone);
        busStatement.setActualArrivalTime(actualArrivalTime);
        busStatement.setCarSeries(carSeries);
        busStatement.setLicensePlate(licensePlate);
        busStatement.setServiceType(serviceType);
        busStatement.setInfo(info);
        busStatement.setAppointmentId(busAppointment.getId());
        //初始结算状态为未支付
        busStatement.setStatus(STATUS_PAID);
        //初始化软删除字段为0
        busStatement.setIsDelete(DELETE_NO);
        //创建时间
        busStatement.setCreateTime(new Date());
        busStatementMapper.generateStatement(busStatement);
        return busStatement.getId();
    }
}
